package com.rich.dmr.server;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Handler;
import android.util.Log;

public class ClientHandler {
    private final String TAG = "rich---ClientHandler";
    private final Socket socket;
    private final ClientReadHandler readHandler;
    private final ClientWriteHandler writeHandler;
    private final ClientHandlerCallback clientHandlerCallback;
    private final String clientInfo;
    private Context mContext;
    private ContentResolver mContentResolver;
    private Handler mHandler;

    ClientHandler(Socket socket,
                  ClientHandlerCallback clientHandlerCallback, Context context, Handler handler)
            throws IOException {
        mContext = context;
        this.socket = socket;
        this.readHandler = new ClientReadHandler(socket.getInputStream());
        this.writeHandler = new ClientWriteHandler(socket.getOutputStream());
        this.clientHandlerCallback = clientHandlerCallback;
        this.clientInfo = "A[" + socket.getInetAddress().getHostAddress()
                + "] P[" + socket.getPort() + "]";
        Log.d(TAG, "新客户端连接：" + clientInfo);
        mHandler = handler;
        mContentResolver =mContext.getContentResolver();
    }

    String getClientInfo() {
        return clientInfo;
    }

    void exit() {
        readHandler.exit();
        writeHandler.exit();
        try {
            socket.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        Log.d(TAG, "客户端已退出：" + socket.getInetAddress() + " P:" + socket.getPort());
    }

    void send(String str) {
        writeHandler.send(str);
    }

    void readToPrint() {
        readHandler.start();
    }

    private void exitBySelf() {
        exit();
        clientHandlerCallback.onSelfClosed(this);
    }

    public interface ClientHandlerCallback {
        // 自身关闭通知
        void onSelfClosed(ClientHandler handler);

        // 收到消息时通知
        void onNewMessageArrived(ClientHandler handler, String msg);
    }

    long time = System.currentTimeMillis();

    class ClientReadHandler extends Thread {
        private boolean done = false;
        private final InputStream inputStream;

        ClientReadHandler(InputStream inputStream) {
            this.inputStream = inputStream;
        }

        @Override
        public void run() {
            super.run();
            try {
                // 得到输入流，用于接收数据
                BufferedReader socketInput = new BufferedReader(
                        new InputStreamReader(inputStream));
                DataInputStream dis = new DataInputStream(inputStream);

                do {
                    // 客户端拿到一条数据
                    // String str = socketInput.readLine();

                    byte[] bytes = new byte[1024];
                    int len;
                    StringBuilder sb = new StringBuilder();
                    try {
                        if ((len = dis.read(bytes)) != -1) {
                            sb.append(new String(bytes, 0, len, "UTF-8"));
                        }
                    } catch (UnsupportedEncodingException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }

                    if (sb.toString().equals("") || sb.toString().length() == 0) {
                        Log.d(TAG, "客户端已无法读取数据！");
                        // 退出当前客户端
                        mHandler.sendEmptyMessage(5);
                        ClientHandler.this.exitBySelf();
                        break;
                    }
                    messageSwitch(sb.toString());
                    // 通知到TCPServer
                    // clientHandlerCallback.onNewMessageArrived(ClientHandler.this,sb.toString());
                } while (!done);
            } catch (Exception e) {
                if (!done) {
                    Log.d(TAG, "连接异常断开！");
                    ClientHandler.this.exitBySelf();
                }
            } finally {
                // 连接关闭
                try {
                    inputStream.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }


        public void messageSwitch(String msg) {
            if ("1000".equals(msg)) {
                mHandler.removeMessages(0);
                mHandler.sendEmptyMessageDelayed(0, 4000);
                writeHandler.send("102");
            } else if (msg.contains("Fre:")) {
                String[] msgs = msg.split("/");
                String channel = msgs[1];
                String freqString = msgs[2];
                if (channel.length() > 0 && freqString.length() > 0) {
                    int frequency =(int)  mul(Double.parseDouble(freqString),1000000);
                    Log.d(TAG, "channel=" + channel + "frequency=" + frequency);
                    if (frequency >= 400000000 && frequency <= 480000000) {
                        if ((frequency % 12500) == 0) {
                            if (findFrequency(frequency) != frequency) {
                                if(insertFrequency(Integer.valueOf(channel),frequency)){
                                    writeHandler.send("channel:" + channel + "  success");
                                    mHandler.sendEmptyMessageDelayed(1, 500);
                                    Log.d(TAG, "data insert success..");
                                } else {
                                    writeHandler.send("channel:" + channel + " fail");
                                    Log.d(TAG, "data insert fail..");
                                }
                            } else {
                                writeHandler.send("channel:" + channel + " exist");
                                Log.d(TAG, "data exist..");
                            }
                        } else {
                            writeHandler.send("channel:" + channel + " data illegal.");
                            Log.d(TAG, "data illegal..");
                        }
                    }else {
                        writeHandler.send("channel:" + channel + " out of range.");
                        Log.d(TAG, "data out of range..");
                    }
                } else {
                    writeHandler.send("channel:" + channel + " no data.");
                    Log.d(TAG, "no data..");
                }
            }else if(msg.contains("color") && msg.contains("group")){
                String[] msgs = msg.split("&");
                String color = msgs[0].split(":")[1];
                mHandler.obtainMessage(3,0,Integer.valueOf(color)).sendToTarget();
                Log.d(TAG, "color="+color);
                if(msgs[1].length() > 6){
                    String group = msgs[1].split(":")[1];
                    if(group.length()<=8){
                        mHandler.obtainMessage(4,0,Integer.valueOf(group)).sendToTarget();
                    }
                    Log.d(TAG, "group="+group);
                }
                writeHandler.send("color:success");
            }
     }

     int findFrequency(int freq){
         Uri freqUri = Uri.parse("content://com.provider.dmr/frequency") ;
         Cursor cursor = mContentResolver.query(freqUri, null, null, new String[]{String.valueOf(freq)} ,null);
         int frequency = 0;
         if (cursor != null) {
             while (cursor.moveToNext()) {
                 frequency = cursor.getInt(cursor.getColumnIndex("frequency"));
                 Log.d(TAG, "frequency =" + frequency);
             }
             cursor.close();
         }
         return frequency;
     }

     boolean insertFrequency(int channel, int frequency){
         ContentValues values=new ContentValues();
         values.put("channel", channel);
         values.put("frequency", frequency);
         Uri uri= mContentResolver.insert(Uri.parse("content://com.provider.dmr/frequency"), values);
         assert uri != null;
         String url = uri.toString();
         String insertUrl = url.substring(url.length()-1);
         return insertUrl.equals("1");
     }

      double mul(double v1, double v2) {
            BigDecimal b1 = new BigDecimal(Double.toString(v1));
            BigDecimal b2 = new BigDecimal(Double.toString(v2));
            return b1.multiply(b2).doubleValue();
       }

    void exit() {
        done = true;
        try {
            inputStream.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

class ClientWriteHandler {
    private boolean done = false;
    private final PrintStream printStream;
    private final ExecutorService executorService;

    ClientWriteHandler(OutputStream outputStream) {
        this.printStream = new PrintStream(outputStream);
        this.executorService = Executors.newSingleThreadExecutor();
    }

    void exit() {
        done = true;
        printStream.close();
        executorService.shutdownNow();
    }

    void send(String str) {
        executorService.execute(new WriteRunnable(str));
    }

    class WriteRunnable implements Runnable {
        private final String msg;

        WriteRunnable(String msg) {
            this.msg = msg;
        }

        @Override
        public void run() {
            if (ClientWriteHandler.this.done) {
                return;
            }

            try {
                ClientWriteHandler.this.printStream.println(msg);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
}
